#include "memory/spw_new.h"
//#include "unwind.h"
#include <cstdlib> // 使用::malloc, ::free
#include <cstdio>

namespace spwstd {
/*
 * NewHandler
 * */
const spwstd::Nothrow_t nothrow = { };

using spwstd::NewHandler;
namespace {
    NewHandler new_handle_;
}

NewHandler setNewHandler(NewHandler handler) noexcept {
    NewHandler prev_handler;
    prev_handler = new_handle_;
    new_handle_ = handler;
    return prev_handler;
}

NewHandler getNewHandler() noexcept {
    NewHandler handler;
    handler = new_handle_;
    return handler;
}

} // namespace spwstd

using spwstd::NewHandler;
using spwstd::spwexcept::BadAlloc;
using ::malloc;

/* 标准的new和delete */
// 抛出异常版本
void* operator new(spwconfig::size_t size) {
    void *p = 0;
    // malloc(0)最好避免出现
    if (size == 0)
        size = 1;

    while((p=malloc(size)) == 0) {
        NewHandler handler = spwstd::getNewHandler();
        if(!handler) {
            handler();
        } else {
            throw BadAlloc();
        }
    }

    return p;
}

void operator delete(void* ptr) noexcept {
    ::free(ptr);
}

void* operator new[](spwconfig::size_t size) {
    return ::operator new(size);
}

void operator delete[](void* ptr) noexcept{
    ::operator delete(ptr);
}

// 不会抛出异常版本
void *operator new(spwconfig::size_t size, const spwstd::Nothrow_t&) noexcept {
    void* p;

    if (size==0)
        size = 1;

    while ((p = malloc(size)) == 0) {
        NewHandler handler = spwstd::getNewHandler();
        if (!handler) {
            handler();
        } 
    }
    return p;
}
void *operator new[](spwconfig::size_t size, const spwstd::Nothrow_t& nothrow) noexcept {
    return ::operator new(size, nothrow);
}

// 当nothrow new 在构造函数时失败，之前分配的内存要释放，会调用该delete
void operator delete(void* ptr, const spwstd::Nothrow_t&) noexcept {
    ::free(ptr);
}
void operator delete[](void* ptr, const spwstd::Nothrow_t&) noexcept {
    ::free(ptr);
}

